package com.bytech.common.config;

import java.sql.SQLException;
import javax.servlet.Filter;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import lombok.extern.slf4j.Slf4j;

import static com.alibaba.druid.support.http.ResourceServlet.*;

/**
 * @Author zhao
 * @Create 2021/7/16 14:52
 */
@Configuration
@Slf4j
@RefreshScope
public class DruidConfig {

    // datasource 配置
    @Value("${mybatis.driver-class-name:com.mysql.cj.jdbc.Driver}")
    private String driverClassName;
    @Value("${mybatis.url}")
    private String url;
    @Value("${mybatis.username}")
    private String username;
    @Value("${mybatis.password}")
    private String password;
    // druid 连接池初始化参数
    @Value("${druid.initial-size:5}")
    private int druidInitialSize;
    @Value("${druid.min-idle:5}")
    private int druidMinIdle;
    @Value("${druid.max-active:5}")
    private int druidMaxActive;
    @Value("${druid.maxWait:60000}")
    private long druidMaxWait;
    @Value("${druid.timeBetweenEvictionRunsMillis:60000}")
    private long druidTimeBetweenEvictionRunsMillis;
    @Value("${druid.minEvictableIdleTimeMillis:300000}")
    private int druidMinEvictableIdleTimeMillis;
    @Value("${druid.maxPoolPreparedStatementPerConnectionSize:20}")
    private int druidMaxPoolPreparedStatementPerConnectionSize;
    @Value("${druid.validationQuery:SELECT 1}")
    private String druidValidationQuery;
    @Value("${druid.testWhileIdle:true}")
    private boolean druidTestWhileIdle;
    @Value("${druid.testOnBorrow:false}")
    private boolean druidTestOnBorrow;
    @Value("${druid.testOnReturn:false}")
    private boolean druidTestOnReturn;
    @Value("${druid.poolPreparedStatements:true}")
    private boolean druidPoolPreparedStatements;
    @Value("${druid.filters}")
    private String druidFilters;

    @Bean
    public DataSource dataSource() throws SQLException {
        return druidDataSource();
    }

    @Bean
    public DruidDataSource druidDataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setInitialSize(druidInitialSize);
        druidDataSource.setMinIdle(druidMinIdle);
        druidDataSource.setMaxActive(druidMaxActive);
        druidDataSource.setMaxWait(druidMaxWait);
        druidDataSource.setTimeBetweenEvictionRunsMillis(druidTimeBetweenEvictionRunsMillis);
        druidDataSource.setMinEvictableIdleTimeMillis(druidMinEvictableIdleTimeMillis);
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(druidMaxPoolPreparedStatementPerConnectionSize);
        druidDataSource.setValidationQuery(druidValidationQuery);
        druidDataSource.setTestWhileIdle(druidTestWhileIdle);
        druidDataSource.setTestOnBorrow(druidTestOnBorrow);
        druidDataSource.setTestOnReturn(druidTestOnReturn);
        druidDataSource.setPoolPreparedStatements(druidPoolPreparedStatements);
        druidDataSource.setFilters(druidFilters);
        log.info("druid pool init:" + druidDataSource);
        return druidDataSource;
    }
}

@Configuration
@Slf4j
class DruidStatViewConfig {

    // druid 可视化界面配置
    @Value("${druid.stat-view-servlet.reset-enable:false}")
    private String resetEnable;
    @Value("${druid.stat-view-servlet.login-username}")
    private String loginUserName;
    @Value("${druid.stat-view-servlet.login-password}")
    private String loginPassword;
    @Value("${druid.stat-view-servlet.url-pattern}")
    private String servletUrlPattern;

    @Bean
    @ConditionalOnProperty(name = "druid.stat-view-servlet.enabled", havingValue = "true")
    public ServletRegistrationBean<StatViewServlet> druidServlet() {
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>();
        servletRegistrationBean.setServlet(new StatViewServlet());
        servletRegistrationBean.addUrlMappings(servletUrlPattern);
        servletRegistrationBean.addInitParameter(PARAM_NAME_ALLOW, "");
        servletRegistrationBean.addInitParameter(PARAM_NAME_DENY, "");
        servletRegistrationBean.addInitParameter(PARAM_NAME_USERNAME, loginUserName);
        servletRegistrationBean.addInitParameter(PARAM_NAME_PASSWORD, loginPassword);
        servletRegistrationBean.addInitParameter("resetEnable", resetEnable);
        log.info("druid state view servlet enabled，servlet init:" + servletRegistrationBean);
        return servletRegistrationBean;
    }

    @Value("${druid.web-stat-filter.exclusions}")
    private String filterExclusions;
    @Value("${druid.web-stat-filter.url-pattern}")
    private String filterUrlPattern;

    @Bean
    @ConditionalOnProperty(name = "druid.web-stat-filter.enabled", havingValue = "true")
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns(filterUrlPattern);
        filterRegistrationBean.addInitParameter("exclusions", filterExclusions);
        return filterRegistrationBean;
    }
}
